package io.xxx.eve.robot;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.xxx.eve.receiver.Receiver;
import io.xxx.eve.robot.send.IPadSender;
import io.xxx.eve.robot.send.PhoneSender;
import io.xxx.eve.task.Task;
import io.xxx.eve.task.TaskMessage;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Triple;
import org.redisson.api.RRateLimiter;

import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;

/**
 * 每一个机器人对应一个Talker，每个Talker维护一个先进先出的队列和一个RateLimiter来控制发送速率
 */
@Slf4j
@AllArgsConstructor
public class Talker implements Runnable {

    private final ArrayBlockingQueue<Triple<Task, Receiver, List<TaskMessage>>> queue = new ArrayBlockingQueue<>(1_000);

    private RRateLimiter rateLimiter;

    private List<TalkLimiter> limiters;

    private IPadSender iPadSender;

    private PhoneSender phoneSender;

    @SneakyThrows
    public void say(Task task, Receiver receiver, List<TaskMessage> messages) {
        queue.put(Triple.of(task, receiver, messages));
    }

    @SneakyThrows
    @Override
    public void run() {
        while (running()) {
            Triple<Task, Receiver, List<TaskMessage>> triple = queue.take();
            Task task = triple.getLeft();
            Receiver receiver = triple.getMiddle();
            List<TaskMessage> messages = triple.getRight();
            for (TaskMessage message : messages) {
                boolean acquire = true;
                for (TalkLimiter limiter : limiters) {
                    acquire = acquire & limiter.tryAcquire();
                }
                if (!acquire) {
                    continue;
                }
                rateLimiter.acquire();
                JSONObject result = switch (task.getSendMode()) {
                    case IPAD -> iPadSender.say(receiver, message);
                    case PHONE -> phoneSender.say(receiver, message);
                };
                log.info("消息发送完成[task:{},result:{}]", JSON.toJSONString(task), result.toJSONString());
            }
        }
    }

    private boolean running() {
        return true;
    }

    /**
     * 发送消息前检查是否可以发送
     */
    public interface TalkLimiter {

        boolean tryAcquire();
    }

    public interface Sender {

        JSONObject say(Receiver receiver, TaskMessage message);
    }
}
